<?php
namespace Core;
use DI\ContainerBuilder;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;

class BeanFactory{
    private static $env=[]; //env 配置文件
    private static $cotainer; //ioc 容器
    private static $handlers=[];
    public static function init() //初始化函数
    {
       self::$env=parse_ini_file(ROOT_PAHT."/env");

        $builder=new ContainerBuilder(); //初始化容器Builder
        $builder->useAnnotations(true); //启用注解，主要是用它的Inject注解
        self::$cotainer=$builder->build(); //容器初始化

        $handlers=glob(ROOT_PAHT . "/core/annotationhandlers/*.php");
        // print_r($handlers);exit;
        /*
            Array
            (
              [0] => /httpapi/14/14code/core/annotationhandlers/AnnotationHandlers.php
              [1] => /httpapi/14/14code/core/annotationhandlers/RequestMapping.php
            )
        */
        foreach ($handlers as $handler){
            self::$handlers=array_merge(self::$handlers,require_once($handler));
        }
        // print_r(self::$handlers);exit;//获取注解处理函数
        /*
Array
(
    [Core\annotations\Bean] => Closure Object
        (
            [parameter] => Array
                (
                    [$instance] => <required>
                    [$container] => <required>
                    [$self] => <required>
                )
        )
    [Core\annotations\Value] => Closure Object
        (
            [parameter] => Array
                (
                    [$prop] => <required>
                    [$instance] => <required>
                    [$self] => <required>
                )
        )
    [Core\annotations\RequestMapping] => Closure Object
        (
            [parameter] => Array
                (
                    [$method] => <required>
                    [$instance] => <required>
                    [$self] => <required>
                )
        )
)
        */

        //设置注解加载类
        $loader = require __DIR__ . '/../vendor/autoload.php';
        AnnotationRegistry::registerLoader([$loader, 'loadClass']);


        $scans=[
            ROOT_PAHT."/core/init"=>"Core\\", //先扫描框架 内部必须要扫描的 文件夹
            self::getEnv("scan_dir",ROOT_PAHT."/app")=>self::getEnv("scan_root_namespace", "App\\")
        ];
        // print_r($scans);exit;
        /*
        Array
        (
            [/httpapi/14/14code/core/init] => Core\
            [./app/controllers] => App\
        )
        */
        //扫描处理有注解的类
        foreach ($scans as  $scan_dir=>$namespace){
            self::ScanBeans($scan_dir,$namespace); //扫描
        }




    }

    private static function getEnv(string $key,string $default=""){ //获取env文件中的配置内容
        if(isset(self::$env[$key])) return self::$env[$key];
        return $default;
    }
    public static function getBean($name){
        return self::$cotainer->get($name);
    }
    public static function ScanBeans($scan_dir,$scan_root_namespace){


        $files=glob($scan_dir."/*.php");
        // print_r($files);exit;
        foreach ($files as $file){
            require_once $file;
        }

        $reader=new  AnnotationReader();

        // print_r(\get_declared_classes());exit;

        foreach (get_declared_classes() as $class){
          if(strstr($class,$scan_root_namespace)) {
            //   print_r($class);echo PHP_EOL;exit;
            /*
                Core\BeanFactory
            */
              $ref_class=new \ReflectionClass($class);//目标类的反射对象
            //   print_r($ref_class);exit;
              /*
              ReflectionClass Object
                (
                    [name] => Core\BeanFactory
                )
              */
              $class_annos=$reader->getClassAnnotations($ref_class);//获取所有类注解
              if($class_annos){
                //   print_r($class_annos);exit;
                  /*
                  Array
                    (
                    [0] => Core\annotations\Bean Object
                        (
                            [name] =>
                        )
                    )
                  */
              }
              /////下方是处理 类注解
              foreach ($class_annos as $class_anno){
                    $handler=self::$handlers[get_class($class_anno)]; //获取handler处理过程
                   $instance=self::$cotainer->get($ref_class->getName());
                //    print_r($ref_class);exit;
                //    print_r($ref_class->getName());exit;
                //    print_r($instance);exit;
                   /*
                   Core\init\RouterCollector Object
                        (
                        [routes] => Array
                        (
                        )

                    )
                   */
                   //处理属性注解
                   self::handlerPropAnno($instance,$ref_class,$reader);
                   //处理方法注解
                     self::handlerMethodAnno($instance,$ref_class,$reader);
                  ///
                    $handler($instance,self::$cotainer,$class_anno); //执行类注解处理
              }
          }
       }
    }
    //处理属性注解
    private static function handlerPropAnno(&$instance,\ReflectionClass $ref_class,AnnotationReader $reader){
        $props=$ref_class->getProperties();//取出反射对象所有属性
        foreach($props as $prop){
            $prop_annos=$reader->getPropertyAnnotations($prop);
            foreach ($prop_annos as $prop_anno){
                $handler=self::$handlers[get_class($prop_anno)];
                $instance=$handler($prop,$instance,$prop_anno);//处理属性注解
            }
        }
    }
    //处理方法注解
    private static function handlerMethodAnno(&$instance,\ReflectionClass $ref_class,AnnotationReader $reader){
        $methods=$ref_class->getMethods();//取出反射对象所有方法
        foreach($methods as $method){
            $method_annos=$reader->getMethodAnnotations($method);
            foreach ($method_annos as $method_anno){
                $handler=self::$handlers[get_class($method_anno)];
                $instance=$handler($method,$instance,$method_anno);//处理方法注解
            }
        }
    }



}